package cn.chinaflame.pagodas.service;



import cn.chinaflame.pagodas.Result.Requests;
import cn.chinaflame.pagodas.Result.Result;
import cn.chinaflame.pagodas.constant.Sysconst;
import cn.chinaflame.pagodas.dto.PaBalmOrderDto;
import cn.chinaflame.pagodas.dto.PaMemberDto;
import cn.chinaflame.pagodas.dto.PaOrderDto;
import cn.chinaflame.pagodas.dto.PaOrderDtoNew;
import cn.chinaflame.pagodas.dto.PaOrderitemDto;
import cn.chinaflame.pagodas.entity.*;
import cn.chinaflame.pagodas.enums.CodeEnum;
import cn.chinaflame.pagodas.handle.HandlerException;
import cn.chinaflame.pagodas.repository.PaBalmOrderRepository;
import cn.chinaflame.pagodas.repository.PaBlessRepository;
import cn.chinaflame.pagodas.repository.PaInvitationRepository;
import cn.chinaflame.pagodas.repository.PaOrderRepository;
import cn.chinaflame.pagodas.repository.PaOrderitemRepository;
import cn.chinaflame.pagodas.repository.PaProductPointRepository;
import cn.chinaflame.pagodas.req.*;
import cn.chinaflame.pagodas.utils.DateTimes;
import cn.chinaflame.pagodas.utils.ParamPreconditions;
import cn.chinaflame.pagodas.utils.ScheduleTime;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author created by lbq
 * @date 2018年1月5日 下午2:56:18
 **/
@Service
public class PaOrderService {


    private static final Logger log = LoggerFactory.getLogger(PaOrderService.class);

    @Autowired
    private PaOrderRepository paOrderRepository;
    @Autowired
    private PaOrderitemRepository paOrderitemRepository;
    @Autowired
    private PaBlessRepository paBlessRepository;
    @Autowired
    private PaOrderitemService paOrderitemService;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private PaMemberService paMemberService;
    @Autowired
    private PaInvitationRepository paInvitationRepository;
    @Autowired
    private PaProductPointService paProductPointService;
    @Autowired
    private IdGeneratorService idGeneratorService;
    @Autowired
    private PaBalmOrderRepository paBalmOrderRepository;
    @Autowired
    private CommonService commonService;
    @Autowired
    private PaProductPointRepository paProductPointRepository;

    public Result<List<PaOrderDto>> queryByPageByJdbc(PaOrderQryReq req) {
        String sql = "SELECT " +
                "o.id as id," +
                "o.member_id as memberId," +
                "o.openid as openid," +
                "o.money as money," +
                "o.order_type as orderType," +
                "o.trans_type as transType," +
                "o.pay_type as payType," +
                "o.pay_status as payStatus," +
                "o.error_msg as errorMsg," +
                "o.item_id as itemId," +
                "i.name as itemName," +
                "o.channel as channel," +
                "o.serial_number as serialNumber," +
                "o.ip as ip," +
                "o.add_time as addTime," +
                "o.pay_time as payTime," +
                "o.pay_finish_time as payFinishTime," +
                "o.createtime as createtime," +
                "o.updatetime as updatetime," +
                /*new_edition 新增 被祝福人姓名和天数*/
                "item.be_wished_name as beWishedName," +
                "item.term as term"
                + " FROM yw_item i, pa_order o, pa_orderitem item WHERE " +
                "i.id = o.item_id and o.id = item.order_id";
        StringBuilder sb = new StringBuilder();
        if (!Strings.isNullOrEmpty(req.getProvinceCode()))
            sb.append(" and i.province_code =").append(req.getProvinceCode());
        if (!Strings.isNullOrEmpty(req.getCityCode()))
            sb.append(" AND i.city_code =").append(req.getCityCode());
        if (!Strings.isNullOrEmpty(req.getAreaCode())) {
            sb.append(" AND i.area_code =").append(req.getAreaCode());
        }
        if (!Strings.isNullOrEmpty(req.getItemId())) {
            sb.append(" AND i.id =").append(req.getItemId());
        }
        sb.append(" ORDER BY o.updatetime DESC");
        JdbcPage<PaOrderDto> page = new JdbcPage<>(sql + sb.toString(), req.getPageSize(), req.getPageIndex(), jdbcTemplate, PaOrderDto.class);

        return Result.createPage(page.getPage(), page.getCount());
    }

    public Result<Integer> queryByPageByJdbcByCount(PaOrderQryReq req) {
        String sql = "SELECT " +
                "o.id as id," +
                "o.member_id as memberId," +
                "o.openid as openid," +
                "o.money as money," +
                "o.order_type as orderType," +
                "o.trans_type as transType," +
                "o.pay_type as payType," +
                "o.pay_status as payStatus," +
                "o.error_msg as errorMsg," +
                "o.item_id as itemId," +
                "o.channel as channel," +
                "o.serial_number as serialNumber," +
                "o.ip as ip," +
                "o.add_time as addTime," +
                "o.pay_time as payTime," +
                "o.pay_finish_time as payFinishTime," +
                "o.createtime as createtime," +
                "o.updatetime as updatetime"
                + " FROM yw_item i, pa_order o WHERE " +
                "i.id = o.item_id";
        StringBuilder sb = new StringBuilder();
        if (!Strings.isNullOrEmpty(req.getProvinceCode()))
            sb.append(" and i.province_code =").append(req.getProvinceCode());
        if (!Strings.isNullOrEmpty(req.getCityCode()))
            sb.append(" AND i.city_code =").append(req.getCityCode());
        if (!Strings.isNullOrEmpty(req.getCityCode())) {
            sb.append(" AND i.area_code =").append(req.getAreaCode());
        }
        if (!Strings.isNullOrEmpty(req.getItemId())) {
            sb.append(" AND i.id =").append(req.getItemId());
        }
        sb.append(" ORDER BY o.updatetime DESC");
        StringBuilder countSql = new StringBuilder();
        countSql.append("select count(*) from (").append(sql).append(") tab");
        jdbcTemplate.execute(countSql.toString());
        long count = jdbcTemplate.queryForObject(countSql.toString(), Long.class);
        return Result.createPage(null, count);
    }

    /**
     * 订单列表查询
     *
     * @return
     */
    public Result<List<PaOrderDto>> query(PaOrderQryReq req) {
        log.info("订单列表查询req:{}");
        List<PaOrder> orders = paOrderRepository.findAll(new Specification<PaOrder>() {
            @Override
            public Predicate toPredicate(Root<PaOrder> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = Lists.newArrayList();
                if (!Strings.isNullOrEmpty(req.getOpenId()))
                    list.add(cb.equal(root.get("openId").as(String.class), req.getOpenId()));
                if (!Strings.isNullOrEmpty(req.getMemberId()))
                    list.add(cb.equal(root.get("memberId").as(String.class), req.getMemberId()));
                if (!Strings.isNullOrEmpty(req.getMobile()))
                    list.add(cb.equal(root.get("mobile").as(String.class), req.getMobile()));
                if (!Strings.isNullOrEmpty(req.getOrderType()))
                    list.add(cb.equal(root.get("orderType").as(String.class), req.getOrderType()));
                if (!Strings.isNullOrEmpty(req.getTranType()))
                    list.add(cb.equal(root.get("tranType").as(String.class), req.getTranType()));
                if (!Strings.isNullOrEmpty(req.getPayType()))
                    list.add(cb.equal(root.get("payType").as(String.class), req.getPayType()));
                if (!Strings.isNullOrEmpty(req.getIp()))
                    list.add(cb.equal(root.get("ip").as(String.class), req.getIp()));
                if (!Strings.isNullOrEmpty(req.getChannel()))
                    list.add(cb.equal(root.get("channel").as(String.class), req.getChannel()));
                Predicate[] p = new Predicate[list.size()];
                return cb.and(list.toArray(p));
            }
        });
        List<PaOrderDto> dtos = Lists.newArrayList();
        for (PaOrder order : orders) {
            PaOrderDto dto = new PaOrderDto();
            BeanUtils.copyProperties(order, dto);
            dtos.add(dto);
        }
        for (int i = 0; i < dtos.size(); i++) {
            List<PaOrderitemDto> itemDtos = Lists.newArrayList();
            List<PaOrderitem> itemList = paOrderitemRepository.findByOrderId(dtos.get(i).getId());
            for (int j = 0; j < itemList.size(); j++) {
                PaOrderitemDto itemDto = new PaOrderitemDto();
                BeanUtils.copyProperties(itemList.get(j), itemDto);
                itemDtos.add(itemDto);
            }
            dtos.get(i).setItemList(itemDtos);
        	List<PaBalmOrder> suborders = paBalmOrderRepository.findByOrderId(dtos.get(i).getId());
        	List<PaBalmOrderDto> orderList = Lists.newArrayList();
        	for(int j=0;j<suborders.size();j++){
        		PaBalmOrderDto subDto = new PaBalmOrderDto();
            	BeanUtils.copyProperties(suborders.get(j), subDto);
            	orderList.add(subDto);
        	}
        	dtos.get(i).setOrderList(orderList);
        }
        return Result.create(dtos);
    }

    /**
     * 订单列表分页查询
     *
     * @return
     */
    public Result<List<PaOrderDto>> queryByPage(PaOrderQryReq req) {
        log.info("订单列表查询req:{}");
        Pageable p = new PageRequest(req.getPageIndex() - 1, req.getPageSize(), new Sort(Direction.DESC, "updatetime"));
        Page<PaOrder> page = paOrderRepository.findAll(new Specification<PaOrder>() {
            @Override
            public Predicate toPredicate(Root<PaOrder> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = Lists.newArrayList();
                if (!Strings.isNullOrEmpty(req.getOpenId()))
                    list.add(cb.equal(root.get("openId").as(String.class), req.getOpenId()));
                if (!Strings.isNullOrEmpty(req.getMemberId()))
                    list.add(cb.equal(root.get("memberId").as(String.class), req.getMemberId()));
                if (!Strings.isNullOrEmpty(req.getMobile()))
                    list.add(cb.equal(root.get("mobile").as(String.class), req.getMobile()));
                if (!Strings.isNullOrEmpty(req.getOrderType()))
                    list.add(cb.equal(root.get("orderType").as(String.class), req.getOrderType()));
                if (!Strings.isNullOrEmpty(req.getTranType()))
                    list.add(cb.equal(root.get("tranType").as(String.class), req.getTranType()));
                if (!Strings.isNullOrEmpty(req.getPayType()))
                    list.add(cb.equal(root.get("payType").as(String.class), req.getPayType()));
                if (!Strings.isNullOrEmpty(req.getIp()))
                    list.add(cb.equal(root.get("ip").as(String.class), req.getIp()));
                if (!Strings.isNullOrEmpty(req.getChannel()))
                    list.add(cb.equal(root.get("channel").as(String.class), req.getChannel()));
                Predicate[] p = new Predicate[list.size()];
                return cb.and(list.toArray(p));
            }
        }, p);
        List<PaOrder> orders = page.getContent();
        List<PaOrderDto> dtos = Lists.newArrayList();
        for (PaOrder order : orders) {
            PaOrderDto dto = new PaOrderDto();
            BeanUtils.copyProperties(order, dto);
            dtos.add(dto);
        }
        for (int i = 0; i < dtos.size(); i++) {
            List<PaOrderitemDto> itemDtos = Lists.newArrayList();
            List<PaOrderitem> itemList = paOrderitemRepository.findByOrderId(dtos.get(i).getId(), new Sort(Direction.DESC, "updatetime"));
            for (int j = 0; j < itemList.size(); j++) {
                PaOrderitemDto itemDto = new PaOrderitemDto();
                BeanUtils.copyProperties(itemList.get(j), itemDto);
                itemDtos.add(itemDto);
            }
            dtos.get(i).setItemList(itemDtos);
        }
        return Result.createPage(dtos, req.getPageIndex(), req.getPageSize(), page.getTotalElements());
    }

    /**
     * 根据id查询单个订单
     *
     * @param id
     * @return
     */
    public PaOrderDto findOrderByid(String id) {
        PaOrder ywOrder = paOrderRepository.findOne(id);
        ParamPreconditions.checkNotNull(ywOrder, CodeEnum.FAIL.getCode(), "未找到订单信息");
        PaOrderDto dto = new PaOrderDto();
        BeanUtils.copyProperties(ywOrder, dto);
        List<PaOrderitem> items = paOrderitemRepository.findByOrderId(dto.getId());
        List<PaOrderitemDto> itemList = Lists.newArrayList();
        for (int i = 0; i < items.size(); i++) {
            PaOrderitemDto itemDto = new PaOrderitemDto();
            BeanUtils.copyProperties(items.get(i), itemDto);
            itemList.add(itemDto);
        }
        dto.setItemList(itemList);
        return dto;
    }
    /**
     * 回调通知业务逻辑
     * @param orderNo
     * @param stateCode
     * @return
     */
    public PaOrderDto orderUpdate(String orderNo, String stateCode){
    	CallbackPaydataReq callbackPaydataReq = new CallbackPaydataReq();
    	callbackPaydataReq.setOrderNo(orderNo);
    	if(Objects.equals(stateCode, "2")){
    		callbackPaydataReq.setPayResult("1");
    	}else{
    		log.info("回调失败，执行撤销操作，待开发stateCode:{}", stateCode);
    		throw new HandlerException(CodeEnum.FAIL.getCode(), "支付回调失败");
    	}
    	PaOrderDto dto = orderUpdate(callbackPaydataReq);
    	//更改会员消费金额和最后消费时间
    	BigDecimal amount = dto.getMoney();
        PaMemberDto oldmember = paMemberService.findOne(dto.getMemberId());
        if (oldmember != null) {
            BigDecimal oldBalance = oldmember.getBalance() == null ? BigDecimal.ZERO : oldmember.getBalance();
            oldmember.setLastConsumeTime(dto.getPayTime());
            oldmember.setBalance(oldBalance.add(amount));
            paMemberService.update1(oldmember);
        }
    	return dto;
    }

    /**
     * 根据订单id更新订单表
     *
     * @param req
     * @return
     */
    public PaOrderDto orderUpdate(CallbackPaydataReq req) {
        log.info("回调通知【service】req:{}", req);
        if (!"1".equals(req.getPayResult())) {
            log.info("回调失败，执行撤销操作，待开发");


            throw new HandlerException(CodeEnum.FAIL.getCode(), "支付回调失败");
        }
        String orderId = req.getOrderNo();
        System.out.println("订单ID为：" + orderId);
        PaOrder ywOrder = paOrderRepository.findPaOrderById(orderId);
        if(ywOrder == null){
        	PaBalmOrder balmOrder = paBalmOrderRepository.findOne(orderId);
        	ParamPreconditions.checkNotNull(balmOrder, CodeEnum.FAIL.getCode(), "支付回调未找到订单信息");
        	if (!Objects.equals(balmOrder.getPayStatus(), Sysconst.PAY_STATUS_DOING)) {
                log.error("错误的订单状态orderId:{},payStatus:{}", balmOrder.getId(), balmOrder.getPayStatus());
                throw new HandlerException(CodeEnum.FAIL.getCode(), "支付回调失败", "支付回调失败-错误的订单状态");
            }
        	PaMember member = paMemberService.findOne(null, null, balmOrder.getOpenid(), null, null, null);
        	balmOrder.setPayStatus(Sysconst.PAY_STATUS_SUC);
        	balmOrder.setPayFinishTime(DateTimes.nowDateTime());
        	balmOrder.setSerialNumber(req.getPaymentOrderId());
        	paBalmOrderRepository.saveAndFlush(balmOrder);
        	PaOrderDto dto = new PaOrderDto();
        	dto.setMemberId(member.getId());
        	dto.setMoney(balmOrder.getMoney());
        	dto.setId(balmOrder.getId());
        	return dto;
        }
        ParamPreconditions.checkNotNull(ywOrder, CodeEnum.FAIL.getCode(), "支付回调未找到订单信息");
//        if (!Objects.equals(ywOrder.getPayStatus(), Sysconst.PAY_STATUS_DOING)) {
//            log.error("错误的订单状态orderId:{},payStatus:{}", ywOrder.getId(), ywOrder.getPayStatus());
//            log.info("回调失败，执行撤销操作，待开发");
//            throw new HandlerException(CodeEnum.FAIL.getCode(), "支付回调失败", "支付回调失败-错误的订单状态");
//        }
        BigDecimal money = (ywOrder.getMoney() != null)?ywOrder.getMoney():new BigDecimal("0.00");
        BigDecimal totalMoney = money.add(new BigDecimal(req.getPayAmount()));
        int size = ywOrder.getTotalMoney().compareTo(totalMoney);
        if (size == 0) {
            ywOrder.setMoney(totalMoney);
            ywOrder.setPayStatus(Sysconst.PAY_STATUS_SUC);
        }else {
            ywOrder.setMoney(totalMoney);
            ywOrder.setPayStatus(Sysconst.PAY_STATUS_PART);
        }

        ywOrder.setPayFinishTime(DateTimes.nowDateTime());
        if (ywOrder.getSerialNumber() == null) {
            ywOrder.setSerialNumber(req.getPaymentOrderId());
        }else {
            ywOrder.setSerialNumber(ywOrder.getSerialNumber()+","+req.getPaymentOrderId());
        }
        paOrderRepository.saveAndFlush(ywOrder);
        //定时任务线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                log.info("线程启动");
                new PaOrder(orderId,new ScheduleTime(5, TimeUnit.SECONDS),Sysconst.PAY_STATUS_WAIT);
            }
        }).start();
        List<PaOrderitem> orderitems = paOrderitemRepository.findByOrderId(orderId);
        ParamPreconditions.checkArgument(orderitems != null && orderitems.size() > 0, CodeEnum.FAIL.getCode(), "未找到订单详情");
        for (int i = 0; i < orderitems.size(); i++) {

            /*new_edition 支付成功寻灯操作start*/
            paProductPointService.findLightByLeftByPayOrder(orderitems.get(i).getId(), orderitems.get(i).getBeWishedName());
            /*end*/

            PaBless bless = paBlessRepository.findByOrderitemId(orderitems.get(i).getId());
            if (!Objects.isNull(bless)) {  //更新祝福信息
                bless.setStatus(Sysconst.BLESS_STATUS_USING);
                bless.setUpdatetime(DateTimes.nowDateTime());
                paBlessRepository.saveAndFlush(bless);
                if (Sysconst.ORDER_TYPE_INVITATION.equals(ywOrder.getOrderType())) {
                    String invitationId = bless.getInvitationId();
                    ParamPreconditions.checkNotEmpty(invitationId, CodeEnum.FAIL.getCode(), "邀请订单邀请id不能为空");
                    PaInvitation invitation = paInvitationRepository.findOne(invitationId);
                    ParamPreconditions.checkNotNull(invitation, CodeEnum.FAIL.getCode(), "未找到邀请信息");
                    invitation.setUpdatetime(DateTimes.nowDateTime());
                    paInvitationRepository.saveAndFlush(invitation);
                }
            }
        }
        PaOrderDto dto = new PaOrderDto();
        BeanUtils.copyProperties(ywOrder, dto);
        return dto;
    }

    /**
     * 添加订单
     *
     * @param req
     * @return
     */
    public PaOrderDto addOrder(OrderAddReq req) {
        req.check();
        String orderId = String.valueOf(System.currentTimeMillis());
        req.setId(orderId);
        req.setPayStatus("0");
        req.setAddTime(DateTimes.nowDate());
        req.setCreatetime(DateTimes.nowDate());
        req.setUpdatetime(DateTimes.nowDate());
        PaOrder ywOrder = new PaOrder();
        BeanUtils.copyProperties(req, ywOrder);
        ywOrder.setAddTime(DateTimes.nowDateTime());
        PaOrderitemReq itemreq = req.getItemlist();
        itemreq.setOrderId(ywOrder.getId());
        PaOrderitemDto itemdto = paOrderitemService.addOrderitem(itemreq);
        ywOrder.setItemId(itemdto.getId());
        ywOrder = paOrderRepository.save(ywOrder);
        PaOrderDto dto = new PaOrderDto();
        BeanUtils.copyProperties(ywOrder, dto);
        return dto;
    }

    /**
     * 添加订单
     *
     * @param req
     * @return
     */
    public Object addOrder(PaOrderAddReq req) {
        //订单参数检查
        req.check();
        //查找会员
        PaMember member = paMemberService.findOne(req.getMemberId(), req.getMobile(), req.getOpenid(), null, null, null);
        PaMemberDto memberDto = new PaMemberDto();
        //判断是否为空
        if (member == null) {
            //为空就注册会员
            PaMemberDto dto = new PaMemberDto();
            dto.setOpenid(req.getOpenid());
            dto.setMobile(req.getMobile());
            dto.setRegistFlg(Sysconst.REGIST_FALSE);
            memberDto = paMemberService.add(dto);
        } else {
            //copy
            BeanUtils.copyProperties(member, memberDto);
        }

        PaOrder entity = new PaOrder();
        //获取会员ID
        String orderId = idGeneratorService.generatePaOrderId();
        entity.setId(orderId);
        entity.setMemberId(memberDto.getId());
        entity.setOpenid(memberDto.getOpenid());
        entity.setMobile(memberDto.getMobile());
        entity.setMoney(new BigDecimal("0.00"));
        entity.setTotalMoney(req.getAmount());
        entity.setOrderType(req.getOrderType());
        //交易方式
        entity.setTransType(req.getTransType());
        entity.setPayType(req.getPayType());
        entity.setPayStatus(Sysconst.PAY_STATUS_WAIT);
        entity.setErrorMsg("");
        //项目ID
        entity.setItemId(req.getItemId());//项目id待确认
        entity.setChannel(req.getChannel());
        entity.setSerialNumber(null);
        entity.setIp(Requests.getRequestAddr());
        entity.setAddTime(DateTimes.nowDateTime());
        entity.setItemId(req.getItemId());
        entity.setPayTime(null);
        entity.setPayFinishTime(null);
        entity.setCreatetime(DateTimes.nowDateTime());
        entity.setUpdatetime(DateTimes.nowDateTime());
        //订单详情
        List<PaOrderItemAddReq> itemList = req.getItemList();
        for (int i = 0; i < itemList.size(); i++) {
            PaOrderitem entityDetail = new PaOrderitem();
            //订单详情ID
            String orderitemId = idGeneratorService.generatePaOrderitemId();
            entityDetail.setId(orderitemId);
            entityDetail.setMemberId(memberDto.getId());
            entityDetail.setOrderId(entity.getId());
            //商品ID
            entityDetail.setProductId(itemList.get(i).getGoodsId());

            entityDetail.setMoney(req.getAmount());
            entityDetail.setNumber(itemList.get(i).getNumber());
            //开始点灯时间
            entityDetail.setStartTime(DateTimes.nowDateTime());
            //根据时间往后推
            String endTime = DateTimes.format(DateUtils.addDays(new Date(), itemList.get(i).getTerm()), DateTimes.TIMESTAMP_PATTERN4);
            entityDetail.setEndTime(endTime);
            entityDetail.setTerm(itemList.get(i).getTerm());
            //祝福人姓名
            entityDetail.setBeWishedName(req.getBlessName());
            entityDetail.setBeWishedSex(req.getBlessSex());
            //祝福人生辰
            entityDetail.setBeWishedBirthday(req.getBlessBirth());
            entityDetail.setBeWishedMobile(req.getBlessPhonenum());
            entityDetail.setBeWishedAddress(req.getBlessAddr());
            entityDetail.setBeWishedMemo(req.getBlessWish());
            entityDetail.setPraying(req.getPraying());
            //设定接口访问状态未1 未掉接口
            entityDetail.setApiStatus("1");
            entityDetail.setCreatetime(DateTimes.nowDateTime());
            entityDetail.setUpdatetime(DateTimes.nowDateTime());
            String locationNos = "";
            /*new_edition 下单寻灯start*/
//            int num = entityDetail.getNumber();

//            for (int k = 0; k < num; k++) {
//                //原下单寻灯
//                PaProductPoint point = paProductPointService.findLightByLeftByAddOrder(entityDetail.getPositionId(), entityDetail.getId());
//                locationNos = "," + point.getLocationNo();
//            }
            Result result = (Result)paProductPointService.getPaProductPointByProductId(itemList.get(i).getGoodsId(),orderitemId);
            if (result.getCode().equals("OK")) {
                PaProductPoint paProductPoint = (PaProductPoint)result.getData();
                locationNos = "," + paProductPoint.getLocationNo();
                entityDetail.setAreaId(paProductPoint.getAreaId());
                entityDetail.setPositionId(paProductPoint.getPositionId());
            }else {
                return Result.create("FALSE",result.getMsg());
            }

            entityDetail.setLocationNo(locationNos.substring(1));
            /*new_edition 下单寻灯end*/
            paOrderitemRepository.saveAndFlush(entityDetail);


            PaBless bless = new PaBless();
            if (Sysconst.ORDER_TYPE_INVITATION.equals(req.getOrderType())) {
                String invitationId = req.getInvitationId();
                PaInvitation invitation = paInvitationRepository.getOne(invitationId);
                invitation.setTargetMemberId(memberDto.getId());
                invitation.setTargetOpenid(memberDto.getOpenid());
                invitation.setUpdatetime(DateTimes.nowDateTime());
                paInvitationRepository.saveAndFlush(invitation);
                bless.setInvitationId(invitationId);
                bless.setBeWishedName(invitation.getBeWishedName());
                bless.setBeWishedSex(invitation.getBeWishedSex());
                bless.setBeWishedBirthday(invitation.getBeWishedBirthday());
                bless.setBeWishedMobile(invitation.getBeWishedMobile());
                bless.setBeWishedAddress(invitation.getBeWishedAddress());
                bless.setBeWishedMemo(invitation.getBeWishedMemo());
            } else {
                bless.setBeWishedName(req.getBlessName());
                bless.setBeWishedSex(req.getBlessSex());
                bless.setBeWishedBirthday(req.getBlessBirth());
                bless.setBeWishedMobile(req.getBlessPhonenum());
                bless.setBeWishedAddress(req.getBlessAddr());
                bless.setBeWishedMemo(req.getBlessWish());
            }
            bless.setItemId(req.getItemId());
            String blessId = String.valueOf(System.currentTimeMillis());
            bless.setId(blessId);
            bless.setSourceMemberId(memberDto.getId());
            bless.setSourceOpenid(memberDto.getOpenid());
            bless.setTargetMemberId(null);
            bless.setTargetOpenid(null);
            bless.setOrderitemId(entityDetail.getId());
            bless.setProductAreaId(itemList.get(i).getAreaId());
            bless.setProductPositionId(itemList.get(i).getPositionId());
            bless.setProductId(itemList.get(i).getGoodsId());
            bless.setSuccess(Sysconst.BLESS_STATUS_UNPAYED);
            bless.setStatus(Sysconst.BLESS_STATUS_UNPAYED);
            bless.setCreatetime(DateTimes.nowDateTime());
            bless.setUpdatetime(DateTimes.nowDateTime());
            paBlessRepository.saveAndFlush(bless);
        }
        entity = paOrderRepository.saveAndFlush(entity);
        //定时任务线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                log.info("线程启动");
                new PaOrder(orderId,new ScheduleTime(30, TimeUnit.MINUTES),Sysconst.PAY_STATUS_WAIT);
            }
        }).start();
		/*ScheduleTime time = new ScheduleTime(15, TimeUnit.MINUTES);
		PaOrderFailure orderFailure = new PaOrderFailure(entity.getId(), Sysconst.PAY_STATUS_WAIT, Sysconst.PAY_STATUS_PAY_TIMEOUT);
		PaOrderSchedule.getInstance().startTask(orderFailure, time);*/
        return Result.create(entity.getId());
    }

    public Object qfjOrderAdd(PaOrderAddReq req){
        PaOrder paOrder = new PaOrder();
        try{
            PaMember member = paMemberService.findOne(req.getMemberId(), req.getMobile(), req.getOpenid(), null, null, null);
            //获取会员ID
            String orderId = idGeneratorService.generatePaOrderId();
            paOrder.setId(orderId);     //编号
            paOrder.setMemberId(member.getId());    //会员ID
            paOrder.setOpenid(member.getOpenid());  //openid
            paOrder.setMobile(member.getMobile());  //手机号
            paOrder.setMoney(new BigDecimal("0.00"));      //金额
            paOrder.setTotalMoney(req.getAmount());//总金额
            paOrder.setOrderType(req.getOrderType());//订单类型
            //交易方式
            paOrder.setTransType(req.getTransType());
            paOrder.setPayType(req.getPayType());   //支付方式
            paOrder.setPayStatus(Sysconst.PAY_STATUS_WAIT);//支付状态
            paOrder.setErrorMsg("");
            //项目ID
            paOrder.setItemId(req.getItemId());//项目id待确认
            paOrder.setChannel(req.getChannel());//交易渠道
            paOrder.setSerialNumber(null);      //支付流水号
            paOrder.setIp(Requests.getRequestAddr());//ip
            paOrder.setAddTime(DateTimes.nowDateTime());//订单下单时间
            paOrder.setPayTime(null);
            paOrder.setPayFinishTime(null);
            paOrder.setCreatetime(DateTimes.nowDateTime());
            paOrder.setUpdatetime(DateTimes.nowDateTime());
            PaOrder primaryOrder = paOrderRepository.findOne(req.getPrimaryOrderId());



            PaOrderitem paOrderitem = new PaOrderitem();
            List<PaOrderitem> list = paOrderitemRepository.findByOrderId(primaryOrder.getId());
            PaOrderitem primaryOrderitem = list.get(0);
            BeanUtils.copyProperties(primaryOrderitem, paOrderitem);
            paOrderitem.setBeWishedMemo(req.getBlessWish());
            String orderitemId = idGeneratorService.generatePaOrderitemId();
            paOrderitem.setId(orderitemId);
            paOrderitem.setOrderId(orderId);


            PaBless bless = new PaBless();
            bless.setBeWishedName(paOrderitem.getBeWishedName());
            bless.setBeWishedSex(paOrderitem.getBeWishedSex());
            bless.setBeWishedBirthday(paOrderitem.getBeWishedBirthday());
            bless.setBeWishedMobile(paOrderitem.getBeWishedMobile());
            bless.setBeWishedAddress(paOrderitem.getBeWishedAddress());
            bless.setBeWishedMemo(paOrderitem.getBeWishedMemo());
            bless.setItemId(req.getItemId());
            String blessId = String.valueOf(System.currentTimeMillis());
            bless.setId(blessId);
            bless.setSourceMemberId(member.getId());
            bless.setSourceOpenid(member.getOpenid());
            bless.setTargetMemberId(null);
            bless.setTargetOpenid(null);
            bless.setOrderitemId(member.getId());
            bless.setProductAreaId(primaryOrderitem.getAreaId());
            bless.setProductPositionId(primaryOrderitem.getPositionId());
            bless.setProductId(primaryOrderitem.getProductId());
            bless.setSuccess(Sysconst.BLESS_STATUS_UNPAYED);
            bless.setStatus(Sysconst.BLESS_STATUS_UNPAYED);
            bless.setCreatetime(DateTimes.nowDateTime());
            bless.setUpdatetime(DateTimes.nowDateTime());
            paBlessRepository.save(bless);
            paOrderitemRepository.save(paOrderitem);
            paOrderRepository.save(paOrder);
            return Result.create(orderId);

        }catch (Exception e){
            log.error("错误消息为：e{}",e);
        }
        return Result.create("FALSE","祈福金下单失败");
    }

    /**
     * 功德榜接口
     */
    public List<Map<String, Object>> merits() {
        String sql = "select tab.*, (@i:=@i+1) as ranking from (" +
                "select member.id as id,member.openid as openid,member.nick_name as name,member.nick_headimgurl as headimgurl,sum(ord.money) as money " +
                "from pa_order ord,pa_member member " +
                "			where ord.member_id=member.id and ord.pay_status=2 and trans_type='PAY' " +
                "			 group by member.id,member.nick_name,member.nick_headimgurl order by sum(ord.money) desc " +
                ") tab,(select   @i:=0)  t2  ";
        List<Map<String, Object>> dtos = jdbcTemplate.queryForList(sql);
        return dtos;
    }

    /**
     * 功德簿供灯数量接口
     *
     * @return
     */
    public List<Map<String, Object>> numberOfLines() {
        String sql = "SELECT tab.*, (@i:=@i+1) AS ranking "
                + "FROM ("
                + "SELECT pm.id AS id,"
                + "pm.openid AS openid,"
                + "pm.nick_name AS name,"
                + "pm.nick_headimgurl AS headimgurl,"
                + "SUM(poi.number) AS number "
                + "FROM pa_order po "
                + "INNER JOIN pa_orderitem poi ON (po.id = poi.order_id) "
                + "INNER JOIN pa_member pm ON (po.member_id=pm.id) "
                + "WHERE po.pay_status=2 AND po.trans_type='PAY' "
                + "GROUP BY pm.id,pm.nick_name,pm.nick_headimgurl "
                + "ORDER BY number DESC) tab,("
                + "SELECT @i:=0) t2";
        List<Map<String, Object>> dtos = jdbcTemplate.queryForList(sql);
        return dtos;
    }

    /**
     * 功德簿供灯天数接口
     *
     * @return
     */
    public List<Map<String, Object>> tremOfLines() {
        String sql = "SELECT tab.*, (@i:=@i+1) AS ranking "
                + "FROM ("
                + "SELECT pm.id AS id,"
                + "pm.openid AS openid,"
                + "pm.nick_name AS name,"
                + "pm.nick_headimgurl AS headimgurl,"
                + "SUM(poi.term) AS term "
                + "FROM pa_order po "
                + "INNER JOIN pa_orderitem poi ON (po.id = poi.order_id) "
                + "INNER JOIN pa_member pm ON (po.member_id=pm.id) "
                + "WHERE po.pay_status=2 AND po.trans_type='PAY' "
                + "GROUP BY pm.id,pm.nick_name,pm.nick_headimgurl "
                + "ORDER BY term DESC) tab,("
                + "SELECT @i:=0) t2";
        List<Map<String, Object>> dtos = jdbcTemplate.queryForList(sql);
        return dtos;
    }

    /**
     * 功德簿分享次数接口
     *
     * @return
     */
    public List<Map<String, Object>> shareOfLines() {
        String sql = "SELECT tab.*, (@i:=@i+1) AS ranking "
                + "FROM ("
                + "SELECT pm.id AS id,"
                + "pm.openid AS openid,"
                + "pm.nick_name AS name,"
                + "pm.nick_headimgurl AS headimgurl,"
                + "COUNT(pi.source_member_id) AS share "
                + "FROM pa_invitation pi "
                + "INNER JOIN pa_member pm ON pm.id = pi.source_member_id "
                + "GROUP BY pm.id,pm.nick_name,pm.nick_headimgurl "
                + "ORDER BY share DESC) tab,("
                + "SELECT @i:=0) t2";
        List<Map<String, Object>> dtos = jdbcTemplate.queryForList(sql);
        return dtos;
    }

    @Transactional(rollbackFor = Exception.class)
    public void notifyOrderStatus(String orderId, String initStatus, String finishStatus) {
        log.info("通知订单状态变更orderId:{},initStatus:{},finishStatus:{}", orderId, initStatus, finishStatus);
        ParamPreconditions.checkNotEmpty(orderId, CodeEnum.FAIL.getCode(), "订单id不能为空");
        PaOrder order = paOrderRepository.findOne(orderId);
        ParamPreconditions.checkNotNull(order, CodeEnum.FAIL.getCode(), "未找到订单信息");
        if (Objects.equals(order.getPayStatus(), initStatus)) {
            //满足变更要求
            order.setPayStatus(finishStatus);
            order.setUpdatetime(DateTimes.nowDateTime());
            paOrderRepository.saveAndFlush(order);
            //执行撤销操作
            log.info("执行撤销操作，待开发");
        }
    }

    /**
     * 查询订单详情接口
     */
    public Result<?> queryOrderItem(String orderId) {
        log.info("查询订单详情orderId:{}", orderId);
        PaOrder orderitem = paOrderRepository.findOne(orderId);
        if (orderitem == null) {
            PaOrderitem orderitem1 = paOrderitemRepository.findOne(orderId);
            ParamPreconditions.checkNotNull(orderitem1, CodeEnum.FAIL.getCode(), "未找到订单详情信息");
            orderId = orderitem1.getOrderId();
        }
        String sql = "SELECT poi.id,poi.be_wished_name,yi.name AS itemname, pp.name AS productname,pp.certificate_photo as certificatePhoto,ppp.name AS posname,ppa.name AS areaname,poi.term,poi.number,poi.start_time,poi.end_time,"
                + " po.money,poi.be_wished_memo,po.pay_finish_time,poi.be_wished_sex,poi.be_wished_birthday,poi.praying,poi.be_wished_mobile FROM pa_order po "
                + " INNER JOIN pa_orderitem poi ON (po.id = poi.order_id)"
                + " INNER JOIN pa_product_position ppp ON (poi.position_id = ppp.id)"
                + " INNER JOIN pa_product_area ppa ON (ppp.area_id = ppa.id)"
                + " INNER JOIN pa_product pp ON (pp.id = poi.product_id)"
                + " INNER JOIN yw_item yi ON (yi.id = pp.item_id)"
                + " where po.id = '" + orderId + "'";
        log.info("sql:"+sql);
        List<Map<String, Object>> dtos = jdbcTemplate.queryForList(sql);
        String nowTime = DateTimes.nowDateTime();
        for(int i=0;i<dtos.size();i++){
        	int wish_status = 1;
        	wish_status = dtos.get(i).get("end_time").toString().compareTo(nowTime);
        	dtos.get(i).put("wish_status", wish_status);
        	String orderitemId = dtos.get(i).get("id").toString();
        	List<PaProductPoint> points = paProductPointRepository.findByOrderitemId(orderitemId);
        	if(points != null && points.size() > 0) {
                String location = "";
                for(int j=0;j<points.size();j++){
//        		0101010101
                    String floor = points.get(j).getLocationNo().substring(0, 2) + "层";
                    String wall = points.get(j).getLocationNo().substring(4, 6) + "墙";
                    String row = points.get(j).getLocationNo().substring(6, 8) + "行";
                    String col = points.get(j).getLocationNo().substring(8, 10) + "列";
                    location = location + ","+floor+ wall + row + col;
                }
                dtos.get(i).put("location", location.substring(1));
            }
        }
        return Result.create(dtos);
    }

    /**
     * po.money,
     * po.id,
     * po.pay_status,
     * po.add_time,
     * po.mobile,
     * 查询订单详情接口（提供给平台）
     */
    public Result<?> queryByPageByJdbc2(PaOrderQryReq req) {
        log.info("查询订单详情orderId:{}", req);
        String sql = "SELECT po.id, po.money, poi.be_wished_name as beWishedName,pp.name as goodsName, po.pay_type AS payType, "
                + "poi.term, po.pay_status AS payStatus, po.add_time AS addTime, "
                + "po.mobile, aa.nick_name AS `name`, bb.start_time as startTime,bb.end_time as endTime "
                + "FROM pa_order po "
                + "INNER JOIN pa_orderitem poi ON (po.id = poi.order_id) "
                + "INNER JOIN pa_product_position ppp ON (poi.position_id = ppp.id) "
                + "INNER JOIN pa_product_area ppa ON (ppp.area_id = ppa.id) "
                + "INNER JOIN pa_product pp ON (pp.id = poi.product_id) "
                + "INNER JOIN pa_member aa ON (po.mobile = aa.mobile)"
                + "INNER JOIN pa_orderitem bb on  (po.id=bb.order_id) WHERE 1 = 1";
        StringBuilder sb = new StringBuilder();
        if (!Strings.isNullOrEmpty(req.getOrderId())) {
            sb.append(" AND po.id = '"+req.getOrderId()+"'");
        }
        if (!Strings.isNullOrEmpty(req.getAddTimeStart())) {
            sb.append(" AND DATE_FORMAT(po.add_time,'%Y-%m-%d') >= '"+req.getAddTimeStart()+"'");
        }
        if (!Strings.isNullOrEmpty(req.getAddTimeEnd())) {
            sb.append(" AND DATE_FORMAT(po.add_time,'%Y-%m-%d') <= '"+req.getAddTimeEnd()+"'");
        }
        sb.append(" ORDER BY po.updatetime DESC");
        JdbcPage<PaOrderDtoNew> page = new JdbcPage<>(sql + sb.toString(), req.getPageSize(), req.getPageIndex(), jdbcTemplate, PaOrderDtoNew.class);
        //List<Map<String, Object>> dtos= jdbcTemplate.queryForList(sql);
        List<PaOrderDtoNew> dtos = page.getPage();
        for(int i=0;i<dtos.size();i++){
        	List<PaBalmOrder> orders = paBalmOrderRepository.findByOrderId(dtos.get(i).getId());
        	List<PaBalmOrderDto> orderList = Lists.newArrayList();
        	for(int j=0;j<orders.size();j++){
        		PaBalmOrderDto subDto = new PaBalmOrderDto();
            	BeanUtils.copyProperties(orders.get(j), subDto);
            	orderList.add(subDto);
        	}
        	dtos.get(i).setOrderList(orderList);
        }
        return Result.createPage(dtos,page.getCount());
        //return Result.create(dtos);
    }

    public Object pmdOrder () {
        log.info("订单跑马灯service");
        try {
            String sql = "SELECT poi.be_wished_name, pp.name " +
                    "FROM pa_order po " +
                    "INNER JOIN pa_orderitem poi ON po.id = poi.order_id " +
                    "INNER JOIN pa_product pp ON poi.product_id = pp.id " +
                    "WHERE po.pay_status = '2' AND poi.start_time <= DATE_FORMAT(SYSDATE(),'%Y-%m-%d %H:%i:%s') " +
                    "AND poi.end_time >= DATE_FORMAT(SYSDATE(),'%Y-%m-%d %H:%i:%s') order by po.pay_finish_time desc";
            List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);

            return Result.create(list);
        }catch (Exception e){
            log.error("错误为：e:{}",e);
        }
        return Result.create("FALSE","查询订单跑马灯接口失败");

    }

    @Transactional(rollbackFor = Exception.class)
    public int orderPayStatusUpdate(String transTimeout, String payTimeout) {
        log.info("定时更新订单状态transTimeout:{},payTimeout:{}", transTimeout, payTimeout);
        List<PaOrder> orders = paOrderRepository.findByPayStatusAndAddTime("0", transTimeout);
        for(int i=0;i<orders.size();i++){
//        	List<PaOrderitem> items = paOrderitemRepository.findByOrderId(orders.get(i).getId());
//        	for(int j=0;j<items.size();j++){
//        		List<PaProductPoint> points = paProductPointRepository.findByOrderitemId(items.get(j).getId());
//        		for(int k=0;k<points.size();k++){
//        			points.get(k).setStatus(Sysconst.POINT_STATUS_INSTALLED);
//        			points.get(k).setOrderitemId(null);
//        			points.get(k).setUpdatetime(DateTimes.nowDateTime());
//        			paProductPointRepository.saveAndFlush(points.get(k));
//        		}
//        	}
        	orders.get(i).setPayStatus(Sysconst.PAY_STATUS_ORDER_TIMEOUT);
        	paOrderRepository.saveAndFlush(orders.get(i));
        }
        List<PaOrder> orders1 = paOrderRepository.findByPayStatusAndAddTime("1", payTimeout);
        for(int i=0;i<orders1.size();i++){
//        	List<PaOrderitem> items = paOrderitemRepository.findByOrderId(orders1.get(i).getId());
//        	for(int j=0;j<items.size();j++){
//        		List<PaProductPoint> points = paProductPointRepository.findByOrderitemId(items.get(j).getId());
//        		for(int k=0;k<points.size();k++){
//        			points.get(k).setStatus(Sysconst.POINT_STATUS_INSTALLED);
//        			points.get(k).setOrderitemId(null);
//        			points.get(k).setUpdatetime(DateTimes.nowDateTime());
//        			paProductPointRepository.saveAndFlush(points.get(k));
//        		}
//        	}
        	orders1.get(i).setPayStatus(Sysconst.PAY_STATUS_PAY_TIMEOUT);
        	paOrderRepository.saveAndFlush(orders1.get(i));
        }
        int result = 0;
        if(orders != null && orders.size() > 0)
        	result = result + orders.size();
        if(orders1 != null && orders1.size() > 0)
        	result = result + orders1.size();
        log.info("定时更新订单状态结果result:{}",result);
//        //-- 更新未支付订单
//        String trans_sql2 = "update pa_order set pay_status='4' where trans_type='PAY' and pay_status='0' and add_time < '" + transTimeout + "'";
//        //-- 更新支付中订单
//        String pay_sql2 = "update pa_order set pay_status='5' where trans_type='PAY' and pay_status='1' and add_time < '" + payTimeout + "'";
//        int[] result = jdbcTemplate.batchUpdate(trans_sql2, pay_sql2);
//        if (result != null && result.length > 0)
//            log.info("定时更新订单状态结果result:{}");
        return result;
    }

}










